// $codepro.audit.disable
package org.mysofts.eclipseman.archives; // $codepro.audit.disable tooManyViolations

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.io.FileUtils;
import org.mysofts.eclipseman.util.AppLog;
import org.mysofts.eclipseman.util.MessageProvider;

/**
 * Classe qui gère des archives au format zip.
 * 
 * @author reda
 * 
 */
final class ZipArchive extends Archive { // $codepro.audit.disable declareDefaultConstructors
	// [start] constructors
	/**
	 * Constructeur.
	 * 
	 * @param pArchive
	 *            Fichier archive.
	 */
	public ZipArchive(final File pArchive) {
		super("zip", pArchive);
	}

	// [end]

	// [start] AbstractArchive Implémentation
	@Override
	public void archive(final File fileToArchive) throws IOException {
		throw new UnsupportedOperationException(MessageProvider.get("logs")
				.sub("archives").sub("zip").sub("archive").sub("unsupported")
				.value());
	}

	@Override
	public Collection<File> extract(final File extractTo) throws IOException {
		AppLog.debug(MessageFormat.format(
				MessageProvider.get("logs").sub("archives").sub("zip")
						.sub("extract").sub("start").value(), this
						.getArchiveFile().getAbsolutePath(), extractTo
						.getAbsolutePath()));
		Collection<File> result = new ArrayList<File>();
		try {
			ZipFile zipFile = new ZipFile(this.getArchiveFile());

			Enumeration<? extends ZipEntry> iter = zipFile.entries();
			while (iter.hasMoreElements()) {
				ZipEntry entry = iter.nextElement();
				File targetFile = new File(extractTo, entry.getName());
				targetFile.getParentFile().mkdirs();
				if (!entry.isDirectory()) {
					InputStream strm = zipFile.getInputStream(entry);
					FileUtils.copyInputStreamToFile(strm, targetFile);
				} else {
					if (targetFile.getParentFile().equals(extractTo)) {
						result.add(targetFile);
					}
				}

			}
			return result;
		} catch (IOException e) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("zip")
							.sub("extract").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), extractTo
							.getAbsolutePath()), e);
			throw e;
		} finally {
			AppLog.debug(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("zip")
							.sub("extract").sub("end").value(), this
							.getArchiveFile().getAbsolutePath(), extractTo
							.getAbsolutePath(), result.toString()));
		}
	}

	@Override
	public Collection<String> listFiles() throws IOException {
		AppLog.debug(MessageFormat.format(
				MessageProvider.get("logs").sub("archives").sub("zip")
						.sub("list").sub("start").value(), this
						.getArchiveFile().getAbsolutePath()));
		List<String> list = new ArrayList<String>();
		try {
			ZipFile zipFile = new ZipFile(this.getArchiveFile());
			Enumeration<? extends ZipEntry> iter = zipFile.entries();
			while (iter.hasMoreElements()) {
				ZipEntry entry = iter.nextElement();
				list.add(entry.getName());
			}
			return list;
		} catch (IOException ex) {
			AppLog.error(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("zip")
							.sub("list").sub("error").value(), this
							.getArchiveFile().getAbsolutePath(), list.size()),
					ex);
			throw ex;
		} finally {
			AppLog.debug(MessageFormat.format(
					MessageProvider.get("logs").sub("archives").sub("zip")
							.sub("list").sub("end").value(), this
							.getArchiveFile().getAbsolutePath(), list.size()));
		}
	}
	
	@Override
	protected Archive instanciate(final File file) {
		return new ZipArchive(file);
	}
	// [end]
}
